Modulo 1 Geostatistica - corso base

Francesco Pirotti

2024-06-17

Introduzione ad R

Cosa impareremo

Materiale

Trovate il materiale in una pagina GitHub QUIe potrete scaricarlo anche come zip ed anche direttamente nello spazio web QUI. Troviamo:

Verrà fornito un link GDrive per caricare gli esercizi per le verifiche.

R: panoramica

R: panoramica

RStudio

Righe codice - i comandi

R è un programma basato su righe di codice con comandi che eseguono elaborazioni su dati.

L’utente immette i comandi al prompt ( > ) e ciascun comando viene eseguito uno alla volta andando a capo.

Le righe di comando solitamente vengono salvate in un file “script” con estensione “R” (.R) e vengono eseguite una alla volta mediante “invio” o con selezione multipla e “invio”.

Con RStudio è possibile eseguire l’intero file, fermandosi eventualmente in punti specifici “breakpoints” (lo vedremo durante il corso).

Esercizio: esegui comando della figura alla slide precedente.

saluto <- "ciao"
print(saluto)
## [1] "ciao"

Commenti e sezioni

Se non si vuole eseguire delle righe, basta mettere un carattere asterisco (#) all’inizio del testo che NON si vuole eseguire.

NB se inserito all’inizio della riga, e seguito da testo e da 4 o più caratteri - o #, il testo diventa una sezione

Documentazione/help

Ogni singola funzione ha ampia documentazione con molti esempi. Chiamando una funzione dopo uno o due punti interrogativi richiama la documentazione. Quasi sempre gli esempi sono eseguibili facendo copia/incolla

Esercizio: esegui il primo esempio dalla documentazione della funzione print

?print
??print

Packages/Librerie

Tantissime funzionalità aggiuntive sono disponibili su componenti aggiuntivi che vanno installate con il comando install.packages(<nome libreria>) e poi caricate con il comando library(<nome libreria>). Da RStudio possiamo caricarle da interfaccia grafica.

Packages/Librerie

Non tutti sono nella “repository” CRAN, alcuni sono su GitHub o scaricabili da altre fonti - vedi alcune cose sotto

Per installare librarie presenti solo in CRAN si utilizza una libreria chiamata “devtools”

# install.packages("devtools")
devtools::install_github("fpirotti/CloudGeometry")

Variabili e funzioni

Qui vediamo una variabile ed una funzione.

NB1 - la variabile “saluto” è nel Environment (“ambito/ambiente/campo”) globale*. La funzione “print” è nel campo del package “base” - tieni premuto il tasto CTRL e seleziona il nome della funzione - vedi cosa succede.

NB2 - operatore di assegnazione <- (o <<- nel caso si voglia forzare l’assegnazione ad una variabile globale*)

Variabili e funzioni: Scope

*Le variabili create al di fuori di funzioni sono note come variabili globali; possono essere utilizzate sia all’interno delle funzioni che all’esterno.

Sotto andiamo a creare una nostra funzione “salutami” che esegue il saluto. Provate a modificare l’operatore di assegnazione da <<- a <<- e rieseguire!!

salutami <- function(){
  saluto <- "ciao ARPA!!!"
  print(saluto)
}

print(saluto)
## [1] "ciao"
salutami()
## [1] "ciao ARPA!!!"
print(saluto)
## [1] "ciao"

Strutture dati in R

NB ogni elemento in R è considerato (ed è) un VETTORE. Le funzioni di R considerano ogni variabile un vettore. Cosa significa? Che le funzioni elaborano tutti gli elementi di un vettore “by default” e che ogni elemento è indicabile con un numero iniziando da 1 (non da 0 come solitamente succede in altri linguaggi).

miaVar <- FALSE
class(miaVar)
miaVar[[1]]
miaVar[[2]]

Tipo dati: vettori

Perchè succede quello che vedete sotto (dati numeric diventano character)?

miaVar <- c(1,4,6,8)
class(miaVar)
## [1] "numeric"
miaVar[[1]]
## [1] 1
miaVar[[2]]
## [1] 4
miaVar[[2]] <- "evviva"
class(miaVar)
## [1] "character"
print(miaVar)
## [1] "1"      "evviva" "6"      "8"

Tipo dati: matrix

Matrix è un oggetto con struttura di matrice ovvero bidimensionale (righe × colonne); pensate a un gruppo di vettori impilati o affiancati.

Si accede e si assegnano i valori con [r,c] dove r e ci sono gli indici di riga e colonna. Si può lasciare vuoto un indice per accedere alla riga/colonna

mat <- matrix(c(1, 2, 3, 4), nrow = 2, ncol = 2)
mat[[2]]
## [1] 2
mat[1,2]
## [1] 3
mat[1,]
## [1] 1 3
mat[1,2] <- 100

Tipo dati: array

Un array è una matrice multidimensionale.

r=rows, c=columns, m=matrice…. etc…

Esercizio: vedi sotto come creare un array a 3 dimensioni. Nota che duplica 9 valori 2 volte. Prova a dare 8 valori invece che nove. Prova a dare 3 valori. Cosa succede.

# 2 vettori di valori 
valori1 <- c(5, 9, 3) 
valori2 <- c(10, 11, 12, 13, 14, 15) 
column.names <- c("C1", "C2", "C3") 
row.names <- c("R1", "R2", "R3") 
matrix.names <- c("Matrix1", "Matrix2") 
  
# Crea un array a tre dimensioni 
arr <- array(c(valori1, valori2), dim = c(3, 3, 2), 
                  dimnames = list(row.names, 
                                  column.names, 
                                  matrix.names)) 
print(arr) 
## , , Matrix1
## 
##    C1 C2 C3
## R1  5 10 13
## R2  9 11 14
## R3  3 12 15
## 
## , , Matrix2
## 
##    C1 C2 C3
## R1  5 10 13
## R2  9 11 14
## R3  3 12 15

Tipo dati: List

Le strutture vector/matrix/array, possono contenere solo una tipologia base (numeric, integer, character, logical…). Ma la struttura LIST no!

La struttura list è un set di dati eterogenei; opzionalmente, è possibile assegnare dei nomi a ciascun elemento nel set.

lista <- list(1,4,6,8)
class(lista)
## [1] "list"
lista[[1]]
## [1] 1
lista[[2]]
## [1] 4
lista[[2]] <- "evviva"
class(lista)
## [1] "list"
lista[[1]]
## [1] 1
lista[[2]]
## [1] "evviva"
print(lista)
## [[1]]
## [1] 1
## 
## [[2]]
## [1] "evviva"
## 
## [[3]]
## [1] 6
## 
## [[4]]
## [1] 8

Tipo dati: List c/nomi

NB, la struttura LIST non è altro che un set, una “lista”, di oggetti associata ad un indice. L’indice è un numero intero ma può essere un testo (simile al concetto di coppie “key->value”/chiave->valore).

Può essere assegnato un indice/chiave per riferimento all’elemento nella lista

names(lista)
## NULL
names(lista) <- c("primo", "secondo")
lista[[1]]
## [1] 1
lista[["primo"]]
## [1] 1

Svantaggi di strutture tipo list: usa più memoria!

Nota su allocazione memoria: se dovete gestire volumi importanti di dati, considerate la pre-allocazione della memoria SE conoscete la dimensione. Vedi anche blog qui.

vettoreMoltoGrande = numeric(1000)
vettoreMoltoGrande[[100]]
## [1] 0

Tipo dati: Data frame

Un data frame è una struttura di tipo list ma con un numero uguale di “righe” per ogni colonna di attributi. È possibile manipolare i data frame filtrando sulle righe e operando sulle colonne.

Sia righe che colonne possono avere identificativi.

 c.lat <- c(45.1, 45.2, 45.3)
 c.lon <- c(11.1, 11.2, 11.3)
 
 df.geo.stz <- data.frame(stz=c("A", "B","C"),
                          longitudine=c.lon,
                          latitudine=c.lat)
 
 colnames(df.geo.stz)
## [1] "stz"         "longitudine" "latitudine"
 rownames(df.geo.stz)
## [1] "1" "2" "3"
 rownames(df.geo.stz) <- df.geo.stz$stz
 rownames(df.geo.stz)
## [1] "A" "B" "C"

Tipo dati: Data frame

Le colonne sono vettori - si può richiamare e assegnare i valori di una colonna con $ o [[]] o [,"<nomecolonna>"] o [ riga,"<nomecolonna>"]

Come con Tipo dati: matrix si possono usare gli indici di riga/colonna.

df.geo.stz$stz
df.geo.stz[,"stz"]
df.geo.stz[["stz"]]
df.geo.stz$stz <- c("A1","B1", "C1")

Tipo dati: Tibble

Un data frame particolare, lo vedremo quando usiamo l’infrastruttura di librerie “tidyverse”. Vantaggi:

library(tidyverse)
geo.stz.tb <- tibble(df.geo.stz)
class(geo.stz.tb)
## [1] "tbl_df"     "tbl"        "data.frame"
#geo.stz.tb
names(data.frame(`nome colonna con spazi` = 1)) 
## [1] "nome.colonna.con.spazi"
names(tibble(`nome colonna con spazi` = 1))
## [1] "nome colonna con spazi"
v <- 1:10
v[]
##  [1]  1  2  3  4  5  6  7  8  9 10
v[] <- 1
v[]
##  [1] 1 1 1 1 1 1 1 1 1 1
v[] <- 1:5
v[]
##  [1] 1 2 3 4 5 1 2 3 4 5
# sotto non funziona!
#v[] <- 1:3

Convertire oggetti

Oggetti tra loro compatibili si possono convertire; ad esempio tra matrix => data.frame usando il comando as.data.frame(<oggetto matrix>) viceversa attenzione che tutti i tipi di vettore vengono resi omogenei.

Provate il seguente esercizio sotto.

mat
##      [,1] [,2]
## [1,]    1  100
## [2,]    2    4
df.mat <- as.data.frame(mat)
as.matrix(df.mat)
##      V1  V2
## [1,]  1 100
## [2,]  2   4
df.mat$nuovaColonna <- "testo"
as.matrix(df.mat)
##      V1  V2    nuovaColonna
## [1,] "1" "100" "testo"     
## [2,] "2" "  4" "testo"
df.mat
##   V1  V2 nuovaColonna
## 1  1 100        testo
## 2  2   4        testo

Salvare oggetti R

Rstudio può salvare l’intero progetto con le variabili e le funzioni che vedete in alto a destra.

Il comando save salva in un file con estensione “rda” che viene riconosciuto anche direttamente da RStudio. NB è possibile salvare qualiasi oggetto, anche funzioni!

Prova a cliccare sul file dopo aver lanciato la prima riga del comando seguente!

## NB salvo anche la funzione "salutami" fatta all'inizio!
save(df.geo.stz, salutami, file="oggetti.rda")
load("oggetti.rda")
saveRDS(df.geo.stz, file = "geo.stz.RDS") 
df.geo.stz <- readRDS("geo.stz.RDS")

Operatori di R

Gli operatori aritmetici e logici di R funzionano sia su singoli scalari che su vettori e strutture come array e matrix.

NB questo vuol dire che si possono eseguire operazioni su tutti i singoli valori della struttura internamente (vectorization)!

c.lat + 10
c.lat == c.lon

c.lat[[1]] <- 44
c.lat <- c.lat - 1
## AND / OR
c.lat == c.lon & c.lat==0
c.lat == c.lon | c.lat==45.1
df.mat$V3 <- df.mat$V2**2
#c.lat == c.lon && c.lat==c.lat
#c.lat == c.lon || c.lat==c.lat 

Esercizio 1

Data in/process/out

Cosa faremo

Impareremo a leggere/trasformare/scrivere dati da fonti diverse:

Input dati: CSV

I file CSV sono notoriamente file di testo strutturati come tabelle e molto utilizzati per condividere dati.

Il comando standard è read.csv .

NB non è ottimizzato per l’efficienza. Per dati massivi usare il comando fread dalla libreria data.table data.table::fread().

Facciamo un esercizio con dati ARPA! Scarichiamo dalla pagina QUI o direttamente da QUI i dati di precipitazione mensile - salvateli in una sottocartella “dati” e caricateli usando sia la funzione read.csv che fread dalla libreria data.table (se l’avete altrimenti vedete a schermo i risultati). Si vuole notare le differenze e come si chiama una funzione SENZA caricare una libreria, usando ::.

prec <- read.csv("dati/Prec_mensili_2020.csv")
prec2 <- data.table::fread("dati/Prec_mensili_2020.csv")
summary(prec2)
##  Precipitazioni mensili Veneto   2020 (mm)      media 1993-2019 (mm)
##  Length:13                     Min.   :   7.0   Min.   :  57.0      
##  Class :character              1st Qu.:  28.0   1st Qu.:  74.0      
##  Mode  :character              Median :  89.0   Median :  96.0      
##                                Mean   : 180.2   Mean   : 171.5      
##                                3rd Qu.: 171.0   3rd Qu.: 114.0      
##                                Max.   :1171.0   Max.   :1114.0

Esercizio: Importate i dati inserendo i parametri corretti di read.csv - come noterete, la prima riga NON importa correttamente. La seconda si, ma è una funzione della libreria data.table. Usate la documentazione in R per capire come aggiungere argomenti alla funzione read.csv (vedi sezione QUI). NB usate il tasto TAB per richiamare i percorsi, risparmiate tempo e fatica!

Input dati: Fogli excel

I fogli di calcolo in formato MS Excel sono più strutturati rispetto ad un file CSV, dato che ogni colonna ha anche lo specifico tipo di dati (numero, testo, data ecc…).

Per leggere/scrivere questi dati è necessario usare librerie aggiuntive.

prec3 <- prec2
## nuova colonna 
prec3$norm2020 <- prec3$`2020 (mm)` / prec3$`media 1993-2019 (mm)`
writexl::write_xlsx( list("originale" =prec2, "elaborata"=prec3), path="dati/output.xlsx" )
prec4 <- readxl::read_xlsx("dati/output.xlsx")

Grafici di base

La funzione plot riesce a creare grafici di base. Andiamo a confrontare le precipitazioni del 2020 con quelle medie 1993-2019.

plot(prec3$`2020 (mm)`[1:12], prec3$`media 1993-2019 (mm)`[1:12], xlab="Prec. 2020 (mm)")
abline(1,1)

Grafici di base

Miglioriamo un po’ il grafico - ma utilizzeremo poi la libreria ggplot2 per ottenere grafici migliori.

plot(prec3$`2020 (mm)`[1:12], prec3$`media 1993-2019 (mm)`[1:12], 
     xlab="Prec. 2020 (mm)", ylab="Prec.media  (mm)",
     xlim=c(0,300), ylim=c(0,300))
abline(1,1)

Input dati: JSON

I dati JSON (JavaScript Object Notation) sono molto utilizzati per trasferire dati non strutturati. Vedi QUI e QUI. Anche per dati “geo” con il GeoJSON (vedi esempio QUI).

Usiamo direttamente da API ARPAV “Anagrafica stazioni in formato JSON” dalla pagina QUI

## Scarichiamo direttamente da API ARPAV
api.url <- "https://api.arpa.veneto.it/REST/v1/meteo_meteogrammi?rete=MGRAMMI&coordcd=18&orario=0&rnd=0.9966091913301682"
stazioni.meteo <- jsonlite::read_json(api.url)

Trasformazione dei dati

Introduzione

Modificare dati significa aggiungere, togliere, filtrare, manipolare colonne, creare sommari e statistiche di interesse aggregando dati. Insomma il dato viene “manipolato”. In inglese viene anche usato “data wrangling”

Ci “alleniamo” con i dati JSON delle stazioni meteo ARPAV scaricati dal JSON.

Obiettivo: creare un grafico con la posizione delle stazioni e aggiungere qualche valore mediante unione con altri dati.

Iteratori

Fondamentale saper utilizzare operazioni che eseguono su tutti gli elementi di un oggetto. E.g. tutte le colonne di un data.frame, tutte le righe di un data.frame, tutti gli oggetti di una list

dati <- stazioni.meteo$data
length(dati)
## LOOP classico: visto male per 
## performance bassa, 
## ma non necessariamente vero
for(i in 1:length(dati)){
  print(dati[[i]])
  break / next
}

funz <- function(x){
  length(x)
}
# lapply/mapply/sapply/apply per righe/colonne
# lapply(dati, funz)

Tidyverse

Introduzione

Tidyverse, dal sito: “un set di funzioni e librerie di R per la data science. Tutti i pacchetti condividono una filosofia di progettazione, una grammatica e strutture di dati”.

La grammatica per la manipolazione dei dati fornisce un insieme coerente di funzioni (verbi) dalla libreria dplyr:

Combinando con group_by() questa operazione viene stratificata “per gruppo” aggregando le operazioni. Ci sono molti altri operatori ma questi sono quelli di base.

Iteratori: map

L’operatore “map” è simile agli “apply” ma con più funzionalità. Vedi sotto, usando map_df i risultati vengono raccolti su una tabella (tibble)!

library(tidyverse)
## i dati sono strutturati nell'oggetto "data" 
##  come liste dentro altre liste
# as.data.frame(stazioni.meteo$data)
dt <- map(.x = stazioni.meteo$data, .f = function(x){ x } ) 
dtf <- map_df (.x = stazioni.meteo$data, .f = function(x){ x } ) 

Iteratori: map

Mappando a data.frame con map abbiamo solo colonne di tipo character… come mai?* NB con map_df questo non succede perchè la funzione map_df è “smart” e capisce qualche tipo usare per ogni colonna. TRANNE che per la colonna valore. Perché?**

NB gli iteratori su tabelle (data.frame o tibble) lavorano per colonne (column-wise).

## richiamo la classe di ogni colonna
# map(.x = dt, .f = function(x){ class(x) } ) 
map(.x = dtf, .f = function(x){ class(x) } ) 
## ATTENZIONE - colonna valore è corretta?
dtf$valore <- as.numeric(dtf$valore)
dtf$tipo <- as.factor(dtf$tipo)
levels(dtf$tipo)

*Perchè raccoglie ogni elemento della lista in un vettore ed il vettore può avere solo valori di un tipo base (character, numeric, integer, logical…) - sceglie sempre il character se valori misti

** Nota che nel JSON il numero in “valore” è tra virgolette, dunque viene visto come testo (character) e non come numerico. Confronta con latitudine e longitudine!

Filter e select

Operazioni usando tidyverse (e altri sistemi) usano operatori di concatenzione di processi. In questo caso si usa %>% ovvero un operatore che indica di usare l’output di un processo come input al processo successivo. Un esempio con un’operazione di filtro con successiva selezione di colonne:

## Selezioniamo solo le stazioni in provincia di Belluno
dtf.belluno <- dtf %>% filter( provincia =="BELLUNO")
## Se aggiungiamo criteri di filtro divisi da virgola è come usare AND 
dtf %>% filter( provincia !="BELLUNO", valore < 10)
dtf %>% filter( provincia !="BELLUNO" & valore < 10)
## Se aggiungiamo criteri di filtro è come usare AND
dtf %>% filter( provincia =="BELLUNO" | valore < 12) %>% select(nome_stazione, valore)

Mutate

Il comando mutate consente di calcolare nuove colonne in funzione di quelle esistenti.

dtf %>% mutate(valore=valore^2)  %>% select(valore)

Aggregazioni

Operazioni di aggregazione con group_by e summarise

Attenzione - la funzione mean restituisce NA se tra i valori trova degli NA, per evitare questo comportamento mettere “na.rm = TRUE”.

dtf %>% group_by(tipo)  %>% summarise(valore=mean(valore))
## # A tibble: 3 × 2
##   tipo    valore
##   <fct>    <dbl>
## 1 TARIA2M   18.1
## 2 TARIA5M   NA  
## 3 TARIA8M   10.8
dtf %>% group_by(tipo)  %>% summarise(valore=mean(valore, na.rm = TRUE))
## # A tibble: 3 × 2
##   tipo    valore
##   <fct>    <dbl>
## 1 TARIA2M  18.1 
## 2 TARIA5M   9.27
## 3 TARIA8M  10.8

Unione tabelle (join)

I join sono operazioni note in ambito di gestione dei dati, servono per aggiungere in senso orizzontale valori usando una o più colonne con valori corrispondenti.

Unione tabelle (join)

Vediamo un esempio pratico: andiamo ad unire i valori di oggi a quelli di alcuni giorni fa alle nostre stazioni. Scarica qui il dato CSV.

dt.past <- read.csv("dati/ARPA_temperatura_20240528.csv")
dt.past <- dt.past %>% select(statnm, statcd, dataora, media)
dt.joined <- dt.past %>%  left_join(dtf, by=c("statcd"="codice_stazione") ) 

Esercizio 2

Ristrutturazione: wide=>long

Questo tipo di modifica è molto comune per rappresentare i dati in modo differente. Vediamo un esempio pratico:

## andiamo a creare classi di temperatura
classi <- cut(dtf$valore, breaks = c(-10,0,10,20,30))
## mappatura con tabella a doppia entrata
tb.wide <- table(dtf$provincia, classi)
## nota che è un oggetto "table", trasformiomo in data.frame
tb.wide <- as.data.frame.matrix(tb.wide)
rownames(tb.wide)
## [1] "BELLUNO" "PADOVA"  "ROVIGO"  "TREVISO" "UDINE"   "VENEZIA" "VERONA" 
## [8] "VICENZA"
## nota ancora che le provincie sono rownames - se converto 
## a tibble non ci sono pià 
rownames(as_tibble(tb.wide) )
## [1] "1" "2" "3" "4" "5" "6" "7" "8"
## creo colonna e relacate la mette all'inizio (provate senza "relocate")
tb.wide <- tb.wide %>% mutate(Provincie = rownames(tb.wide))%>%  relocate(Provincie)
## tabella con numero di stazioni per classe espressa "wide" 
tb.wide
##         Provincie (-10,0] (0,10] (10,20] (20,30]
## BELLUNO   BELLUNO       0     16      32       0
## PADOVA     PADOVA       0      0       0      10
## ROVIGO     ROVIGO       0      0       0       6
## TREVISO   TREVISO       0      0       4      12
## UDINE       UDINE       0      0       1       0
## VENEZIA   VENEZIA       0      0       4      11
## VERONA     VERONA       0      0       4       9
## VICENZA   VICENZA       0      0      26      10
## trasformo 
tb.long <- tb.wide  %>% pivot_longer(!Provincie, 
    names_to = "Classe Temp. °C", values_to = "Numero"
    )
tb.long
## # A tibble: 32 × 3
##    Provincie `Classe Temp. °C` Numero
##    <chr>     <chr>              <int>
##  1 BELLUNO   (-10,0]                0
##  2 BELLUNO   (0,10]                16
##  3 BELLUNO   (10,20]               32
##  4 BELLUNO   (20,30]                0
##  5 PADOVA    (-10,0]                0
##  6 PADOVA    (0,10]                 0
##  7 PADOVA    (10,20]                0
##  8 PADOVA    (20,30]               10
##  9 ROVIGO    (-10,0]                0
## 10 ROVIGO    (0,10]                 0
## # ℹ 22 more rows

Ristrutturazione: long=>wide

Operazione inversa per tornare alla tabella di origine

tb.long2wide <- tb.long  %>% pivot_wider( 
  names_from = "Classe Temp. °C", values_from = "Numero"
  )
tb.long2wide
## # A tibble: 8 × 5
##   Provincie `(-10,0]` `(0,10]` `(10,20]` `(20,30]`
##   <chr>         <int>    <int>     <int>     <int>
## 1 BELLUNO           0       16        32         0
## 2 PADOVA            0        0         0        10
## 3 ROVIGO            0        0         0         6
## 4 TREVISO           0        0         4        12
## 5 UDINE             0        0         1         0
## 6 VENEZIA           0        0         4        11
## 7 VERONA            0        0         4         9
## 8 VICENZA           0        0        26        10

Grafici

Grafici con GGplot - dispersione

Le funzioni di base “plot” sono utili ma ci sono librerie che forniscono più funzionalità. Introduciamo “ggplot”. Notate che viene creato un grafico concatenando con l’operatore “+” gli oggetti del grafico. “aes” sta per aestethics e indica colori e valori degli assi, aggregazioni ecc…

library(ggplot2)
ggplot(dtf, aes(x=quota, y=as.numeric(valore))) + geom_point( ) + 
  geom_smooth(method = "lm")+ theme_bw()

Grafici con GGplot - scatola e baffi

NB. la parte “as.numeric” in quanto la colonna anche contiene numeri è di tipo “character”. Modifichiamola con “as.numeric”, ma vedrete due valori mancanti (NA=not available).

dtf$valore <- as.numeric(dtf$valore)
ggplot(dtf) + geom_boxplot(aes(x=tipo, y=valore )) + theme_bw()

Grafici multipli (facets)

facet_wrap e facet_grid consentono di “esplodere” per una o più variabili di raggruppamento. Qui un esempio con una stima della funzione di distribuzione delle frequenze.

ggplot(dtf) + geom_density(aes(x=valore )) + theme_bw()

ggplot(dtf) + geom_density(aes(x=valore)) + facet_wrap(vars(tipo)) + theme_bw() 

Grafici multipli (facets)

facet_wrap e facet_grid consentono di “esplodere” per una o più variabili di raggruppamento.

 ggplot(dtf) + geom_density(aes(x=valore)) + facet_grid(provincia~tipo ) + theme_bw()

Grafici e dati geo

Abbiamo colonne con coordinate: possiamo creare un grafico con uno sfondo territoriale e considerare delle colonne come coordinate? Per dati geo usiamo libreria sf e terra. Non indispensabili per geostatistica, ma fortemente consigliati.

library(ggspatial, quietly = T)
library(sf)  ## se non l'avete installata non vi preoccupate 
theme_set(theme_bw())
ggplot(dtf) + geom_point(aes(x=longitudine, y=latitudine, color=valore, size=valore )) 

dtf.geo <- sf::st_as_sf(dtf,coords = c("longitudine","latitudine"), crs=4326 )
ggplot(dtf.geo) + geom_sf(aes(color=valore, size=valore )) + coord_sf()

Grafici e stampe PNG

Il metodo per avere grafici su stampa mediante immagini o pdf

png("fileGrafico.png")

 p <- ggplot(dtf.geo) + geom_sf(aes(color=valore, size=valore )) + coord_sf()
 print(p)
dev.off()

possiamo impostare dimensioni in pixel (width e height) ed inoltre la risoluzione (res)… provate a vedere.

png("fileGrafico300dpi.png", width=2000, height=2000, res=300)   
  p <- ggplot(dtf.geo) + geom_sf(aes(color=valore, size=valore )) + coord_sf()  
  print(p) 
dev.off()

Grafici e stampe PDF

Il formato PDF ha il vantaggio/svantaggio di essere vettoriale (non perde definizione) - provate a vedere la definizione. Perchè non usiamo SEMPRE pdf? Immaginatevi a inserire milioni di punti… perde efficacia.

pdf("fileGrafico.pdf")  
  p <- ggplot(dtf.geo) + geom_sf(aes(color=valore, size=valore )) + coord_sf()  
  print(p) 
dev.off()

NB possiamo creare un iterazione per fare un grafico per foglio in un singolo file PDF!

plotMe <- function(tipoStazione){
  dati <- dtf.geo %>% filter(tipo==tipoStazione) 
  p <- ggplot(dati) + geom_sf(aes(color=valore)) + ggtitle(paste("Tipo: ", tipoStazione)) + coord_sf() 
  p
}
## NB la colonna "tipo" è di tipo FACTOR
pdf("fileGraficoMulti.pdf")  
    for(tipoStz in levels(dtf.geo$tipo) ){
      p <- plotMe(tipoStz)
      print(p)
    } 
dev.off()

Cheatsheets

Sono PDF formato poster con indicazioni di base sull’utilizzo di strumenti R

Esercizio 3

Vedi i due file nella cartella “esercizi/modulo1” - eseguirete il seguente grafico estraendo i dati dalle API meteo ARPAV.

Dati geospaziali

Introduzione

A grandi linee i dati spaziali sono interpretati digitalmente mediante due modelli: il modello vettoriale ed il modello raster. In entrambi i casi va comunque compreso che ogni elemento è georiferito, ovvero ha una localizzazione in un sistema di riferimento, quindi delle coordinate.

Dati vettoriali

I dati vettoriali hanno tre primitive geometriche di base: punti linee e poligoni. La base è sempre il punto con una coordinate, in 2d o 3d.

Ci sono decine di formati di file che rappresentano dati vettoriali. Ne abbiamo visto uno all’inizio, il file JSON! Per un riferimento vedete la pagina QUI. Ad oggi la libreria di riferimento per leggere questi dati è la libreria sf.

Raster

Il formato raster è molto semplice: sono nodi a passo costante, quindi una “griglia” georiferita mediante uno o più punti. Il passo della griglia è spesso identico nelle due direzioni (ma non necessariamente), e ne determina la risoluzione spaziale.

Ci sono decine di formati di file che rappresentano dati raster. Per un riferimento vedete la pagina QUI. Ad oggi la libreria di riferimento per leggere questi dati è la libreria terra.